#ifndef HEAD_H
#define HEAD_H

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/select.h>
#include <time.h>
#include <sys/wait.h>
#include <dirent.h>
#include <syslog.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <signal.h>
#include <sys/time.h>
#include <pthread.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/epoll.h>
#include <sys/sendfile.h>

#define ARGS_CHECK(argc, num)                  \
    {                                          \
        if (argc != num)                       \
        {                                      \
            fprintf(stderr, "args error !\n"); \
            return -1;                         \
        }                                      \
    }
#define ERROR_CHECK(ret, num, msg) \
    {                              \
        if (ret == num)            \
        {                          \
            perror(msg);           \
            return -1;             \
        }                          \
    }
#define THREAD_ERROR_CHECK(ret, msg)                         \
    {                                                        \
        if (ret != 0)                                        \
        {                                                    \
            fprintf(stderr, "%s:%s \n", msg, strerror(ret)); \
        }                                                    \
    }

typedef enum
{
    LOGIN, // 登录
    CD,
    LS,
    PUTS,
    GETS,
    RM,
    PWD,
    MKDIR,
    EXIT,
} request_type;

// 请求报文
typedef struct
{
    request_type flag;  // 请求类型
    char user_name[60]; // 用户名
    char args[60];      // 指令携带的参数
    char path[100];     // 客户端所在的虚拟路径名
} request_t;

typedef struct
{
    int status;
    char args[1024]; // 服务端返回的参数
} response_t;

/**
  配置文件
 * @return int 成功返回0，失败返回-1
 */
int load_config(char *key, char *value);

/**
 * @brief 分析stdin读入的字符串
 * @param str 标准输入读取的字符串
 * @param cmd 解析后的命令(传入传出)
 * @param arg 解析后的参数(例如:路径,文件名)
 * @return int 成功返回0，失败返回-1
 */
int analyze_cmd(int net_fd, char *str, request_t *request);
/**
 * @brief 获取命令类型
 * @param cmd传入的命令
 * @return int 返回对应的枚举变量，未识别的返回-1
 */
int get_type(char *cmd);
/**
 * @brief cd命令的逻辑
 * @param dest 要切换的目标路径
 * @param curr_path 当前路径
 * @return int 成功返回0，失败返回-1
 */
int net_cd(int net_fd, char *path, request_t *request);

/**
 * @brief ls命令的逻辑
 * @param curr_path 当前路径
 * @return int 成功返回0，失败返回-1
 */

int net_ls(int net_fd, request_t *request);

/**
 * @brief puts将本地文件上传至服务器
 * @param curr_path 当前路径
 * @param file_name 要上传的文件名
 * @return int 成功返回0，失败返回-1
 */
int net_puts(int net_fd, char *file_name, request_t *request);

/**
 * @brief gets将服务器上的文件下载至本地
 * @param curr_path 当前路径
 * @param file_name 要下载的文件名
 * @return int 成功返回0，失败返回-1
 */
int net_gets(int net_fd, char *file_name, request_t *request);

/**
 * @brief rm命令的逻辑
 * @param curr_path 当前路径
 * @param file_name 要删除的文件名
 * @return int 成功返回0，失败返回-1
 */
int net_rm(int net_fd, char *file_name, request_t *request);

/**
 * @brief pwd命令的逻辑
 * @param curr_path 当前路径
 * @return int 成功返回0，失败返回-1
 */
int net_pwd(int net_fd, request_t *request);

// 创建文件夹
int net_mkdir(int net_fd, char *file_name, request_t *request);

//接收服务端传来的文件
int recv_file(const char *file_name, int socket_fd);

//向服务端发送文件
int send_file(const char *file_name, int socket_fd); 
#endif
